package org.zn.note.designpattern;

/**
 * 责任链模式（Chain of Responsibility Pattern）
 */
public class Pattern14_Chain {

    public static void main(String[] args) {
        // 创建一个日志链
        AbstractLogger log = new Log(); // 创建一个“头节点”，什么都不做
        log.nextLogger(new ConsoleLogger()) // 每个节点，就是一种实现
                .nextLogger(new FileLogger())
                .nextLogger(new ErrorLogger());
        // 传入日志等级，请求会沿着“链”传递下去，每个“链”中的“节点”是具体实现，根据条件处理自己能处理的
        log.logMessage(AbstractLogger.INFO, "This is an information.");
        log.logMessage(AbstractLogger.DEBUG, "This is a debug level information.");
        log.logMessage(AbstractLogger.ERROR, "This is an error information.");
    }

    private static class Log extends AbstractLogger {
        @Override
        void write(String message) {
            // nothing
        }
    }

    private static abstract class AbstractLogger {
        static int INFO = 1;
        static int DEBUG = 2;
        static int ERROR = 3;

        int level;

        //责任链中的下一个元素
        AbstractLogger nextLogger;

        AbstractLogger nextLogger(AbstractLogger nextLogger) {
            this.nextLogger = nextLogger;
            return nextLogger;
        }

        void logMessage(int level, String message) {
            if (this.level <= level) {
                write(message);
            }
            if (nextLogger != null) {
                nextLogger.logMessage(level, message);
            }
        }

        abstract void write(String message);
    }

    private static class ConsoleLogger extends AbstractLogger {
        ConsoleLogger() {
            super.level = AbstractLogger.INFO;
        }

        @Override
        void write(String message) {
            System.out.println("Standard Console::Logger: " + message);
        }
    }

    private static class ErrorLogger extends AbstractLogger {
        ErrorLogger() {
            super.level = AbstractLogger.ERROR;
        }

        @Override
        void write(String message) {
            System.out.println("Error Console::Logger: " + message);
        }
    }

    private static class FileLogger extends AbstractLogger {
        FileLogger() {
            super.level = AbstractLogger.DEBUG;
        }

        @Override
        void write(String message) {
            System.out.println("File::Logger: " + message);
        }
    }
}
